﻿// <copyright file="Square.xaml.cs" company="ALCPU">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <author>Arthur Liberman</author>
// <email>Arthur_Liberman@hotmail.com</email>
// <date>04-03-2010</date>
// <summary>Contains Square control code-behind.</summary>

namespace Chess
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

    /// <summary>
    /// Describes a display mode of the <see cref="Square"/> class.
    /// </summary>
    public enum SquareDisplayMode
    {
        /// <summary>
        /// In normal display mode.
        /// </summary>
        Normal,

        /// <summary>
        /// In the attack mode.
        /// </summary>
        Attack,

        /// <summary>
        /// In the available mode.
        /// </summary>
        Available,

        /// <summary>
        /// In the selected mdoe 
        /// </summary>
        Selected
    }

    /// <summary>
    /// Interaction logic for Square.xaml
    /// </summary>
    public partial class Square : UserControl
    {
        /// <summary>
        /// The HighlightMode dependancy property.
        /// </summary>
        private static readonly DependencyProperty HighlightModeProperty;

        /// <summary>
        /// The HighlightMode dependancy property.
        /// </summary>
        private static readonly DependencyProperty ImageProperty;

        /// <summary>
        /// The AvailableHide Storyboard.
        /// </summary>
        private readonly Storyboard availableHide;

        /// <summary>
        /// The AttackHide Storyboard.
        /// </summary>
        private readonly Storyboard attackHide;

        /// <summary>
        /// The SelectHide Storyboard.
        /// </summary>
        private readonly Storyboard selectHide;

        /// <summary>
        /// The GlowPulseAttack Storyboard.
        /// </summary>
        private readonly Storyboard glowPulseAttack;

        /// <summary>
        /// The GlowPulseSelect Storyboard.
        /// </summary>
        private readonly Storyboard glowPulseSelect;

        /// <summary>
        /// Keeps the original opacity level of the "Selection" mask.
        /// </summary>
        private Brush availableBrush;

        /// <summary>
        /// Initializes static members of the <see cref="Square"/> class.
        /// </summary>
        static Square()
        {
            PropertyChangedCallback changedCallback =
                new PropertyChangedCallback(HighlightModeChanged);
            PropertyMetadata metaData =
                new PropertyMetadata(changedCallback);
            HighlightModeProperty = DependencyProperty.Register(
               "HighlightMode",
               typeof(SquareDisplayMode),
               typeof(Square),
               metaData);

            changedCallback = new PropertyChangedCallback(ImageChanged);
            metaData = new PropertyMetadata(changedCallback);
            ImageProperty = DependencyProperty.Register(
               "Image",
               typeof(Brush),
               typeof(Square),
               metaData);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Square"/> class.
        /// </summary>
        public Square()
        {
            this.InitializeComponent();
            this.availableBrush = this.availableRect.Stroke.Clone();
            this.availableHide = this.FindResource("AvailableHide") as Storyboard;
            this.attackHide = this.FindResource("AttackHide") as Storyboard;
            this.selectHide = this.FindResource("SelectHide") as Storyboard;
            this.glowPulseAttack = this.FindResource("GlowPulseAttack") as Storyboard;
            this.glowPulseSelect = this.FindResource("GlowPulseSelect") as Storyboard;
            this.availableHide.Completed += new EventHandler(this.AvailableHide_Completed);
            this.attackHide.Completed += new EventHandler(this.AttackHide_Completed);
            this.selectHide.Completed += new EventHandler(this.SelectHide_Completed);
            this.DisplayMode = SquareDisplayMode.Normal;
        }

        /// <summary>
        /// Gets or sets the image for this square.
        /// </summary>
        /// <value>The image.</value>
        public Brush Image
        {
            get { return (Brush)this.GetValue(ImageProperty); }
            set { this.SetValue(ImageProperty, value); }
        }

        /// <summary>
        /// Gets or sets the current display mode of the square.
        /// </summary>
        /// <value>The new display mode.</value>
        public SquareDisplayMode DisplayMode { get; protected set; }

        /// <summary>
        /// Gets or sets the current highlight mode of the square.
        /// </summary>
        /// <value>The new display mode.</value>
        public SquareDisplayMode HighlightMode
        {
            get { return (SquareDisplayMode)this.GetValue(HighlightModeProperty); }
            set { this.SetValue(HighlightModeProperty, value); }
        }

        /// <summary>
        /// Highlight square using indicating that it is available.
        /// </summary>
        public void ShowAvailable()
        {
            this.ShowNormal(false);
            this.DisplayMode = SquareDisplayMode.Available;
            this.availableRect.Stroke = this.availableBrush.Clone();
            this.availableRect.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Highlight square using indicating that it is attackable.
        /// </summary>
        public void ShowAttackable()
        {
            this.ShowNormal(false);
            this.DisplayMode = SquareDisplayMode.Attack;
            this.attackRect.Visibility = Visibility.Visible;
            this.glowPulseAttack.Begin();
        }

        /// <summary>
        /// Highlight square using indicating that it is selected.
        /// </summary>
        public void ShowSelected()
        {
            this.ShowNormal(false);
            this.DisplayMode = SquareDisplayMode.Selected;
            this.selectRect.Visibility = Visibility.Visible;
            this.glowPulseSelect.Begin();
        }

        /// <summary>
        /// Display square normally.
        /// </summary>
        public void ShowNormal()
        {
            this.ShowNormal(true);
        }

        /// <summary>
        /// Handles the notification of the HighlightMode property change.
        /// </summary>
        /// <param name="square">The square.</param>
        /// <param name="ea">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private static void HighlightModeChanged(DependencyObject square, DependencyPropertyChangedEventArgs ea)
        {
            switch ((SquareDisplayMode)ea.NewValue)
            {
                case SquareDisplayMode.Normal:
                    (square as Square).ShowNormal();
                    break;
                case SquareDisplayMode.Available:
                    (square as Square).ShowAvailable();
                    break;
                case SquareDisplayMode.Attack:
                    (square as Square).ShowAttackable();
                    break;
                case SquareDisplayMode.Selected:
                    (square as Square).ShowSelected();
                    break;
            }
        }

        /// <summary>
        /// Handles the notification of the Image property change.
        /// </summary>
        /// <param name="square">The square.</param>
        /// <param name="ea">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private static void ImageChanged(DependencyObject square, DependencyPropertyChangedEventArgs ea)
        {
            (square as Square).imageRect.Fill = (Brush)ea.NewValue;
        }

        /// <summary>
        /// Display square normally.
        /// </summary>
        /// <param name="animate">if set to <c>true</c> animate the square being hidden.</param>
        private void ShowNormal(bool animate)
        {
            this.glowPulseSelect.Stop();
            this.glowPulseAttack.Stop();
            if (animate && this.DisplayMode != SquareDisplayMode.Normal)
            {
                switch (this.DisplayMode)
                {
                    case SquareDisplayMode.Attack:
                        this.attackHide.Begin();
                        break;
                    case SquareDisplayMode.Selected:
                        this.selectHide.Begin();
                        break;
                    case SquareDisplayMode.Available:
                        this.availableHide.Begin();
                        break;
                }
            }
            else
            {
                this.selectRect.Visibility = Visibility.Hidden;
                this.availableRect.Visibility = Visibility.Hidden;
                this.attackRect.Visibility = Visibility.Hidden;
            }

            this.DisplayMode = SquareDisplayMode.Normal;
        }

        /// <summary>
        /// Handles the Completed event of the AvailableHide animation.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AvailableHide_Completed(object sender, EventArgs e)
        {
            if (this.DisplayMode != SquareDisplayMode.Available)
            {
                this.availableRect.Visibility = Visibility.Hidden;
            }
        }

        /// <summary>
        /// Handles the Completed event of the AttackHide animation.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AttackHide_Completed(object sender, EventArgs e)
        {
            if (this.DisplayMode != SquareDisplayMode.Attack)
            {
                this.attackRect.Visibility = Visibility.Hidden;
            }
        }

        /// <summary>
        /// Handles the Completed event of the SelectHide animation.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void SelectHide_Completed(object sender, EventArgs e)
        {
            if (this.DisplayMode != SquareDisplayMode.Selected)
            {
                this.selectRect.Visibility = Visibility.Hidden;
            }
        }
    }
}